#include<cmath>
#include<limits>
#include<iostream>
const double pi = acos(-1.0);

//基类
class EquationSolver
{
public:
	virtual double solve() = 0;
};

//符号函数
int sgn(double x) {
	if (x > 0)
		return 1;
	else if (x < 0)
		return -1;
	else return 0;
}

//func1到func4为B题的四个函数
double func1(double x)
{
	return 1 / x - tan(x);
}

double func2(double x)
{
	return 1 / x - pow(2, x);
}

double func3(double x)
{
	return pow(2, -x) + exp(x) + 2 * cos(x) - 6;
}

double func4(double x)
{
	return (pow(x, 3) + 4 * pow(x, 2) + 3 * x + 5) / (2 * pow(x, 3) - 9 * pow(x, 2) + 18 * x - 2);
}

//func5和diff5是C题的函数以及导数
double func5(double x)
{
	return (tan(x) - x);
}
double diff5(double x)
{
	return (1 / pow(cos(x), 2) - 1);
}

//func6到func8是D题的三个函数
double func6(double x)
{
	return sin(x / 2) - 1;
}
double func7(double x)
{
	return exp(x) - tan(x);
}
double func8(double x)
{
	return pow(x, 3) - 12 * pow(x, 2) + 3 * x + 1;
}

//func9与diff9为第E题的函数及导数
double func9(double x)
{
	return asin(x) + x * sqrt(1 - x*x) + 1.24 - 0.5 * pi;
}
double diff9(double x)
{
	return 2 * sqrt(1 - x * x);
}
//func10和diff10为第F题的函数及导数
double func10(double x, double l, double h, double D, double beta)
{
	beta = beta * pi / 180;
	double A = l * sin(beta),
		B = l * cos(beta),
		C = (h + 0.5 * D) * sin(beta) - 0.5 * D * tan(beta),
		E = (h + 0.5 * D) * cos(beta) - 0.5 * D;
	return A * sin(x) * cos(x) + B * pow(sin(x), 2) - C * cos(x) - E * sin(x);
}
double diff10(double x, double l, double h, double D, double beta)
{
	beta = beta * pi / 180;
	double A = l * sin(beta),
		B = l * cos(beta),
		C = (h + 0.5 * D) * sin(beta) - 0.5 * D * tan(beta),
		E = (h + 0.5 * D) * cos(beta) - 0.5 * D;
	return A * cos(2 * x) + B * sin(2 * x) + C * sin(x) - E * cos(x);
}

//二分法
class Bisection : public EquationSolver
{
private:
	double a, b, delta,h=0,u=0,w=0,c=0;
	int M=0,k=0;
public:
	Bisection(double _a, double _b, double _delta, int _M):a(_a),b(_b),delta(_delta),M(_M) {};
	double solve() {
		h = b - a;
		u = func1(a);
		for (k = 1; k < M; k++) {
			h = h / 2;
			c = a + h;
			w = func1(c);
			if (abs(h) < delta || abs(w) < std::numeric_limits<double>::epsilon()) {
				break;
			}
			else if (sgn(w) == sgn(u))
				a = c;
		}
		if (k >= M) {
			std::cout << "不收敛" << std::endl;
		}
		else {
			std::cout << "根为：" <<c<< std::endl;
			std::cout << "迭代次数为：" << k << std::endl;
		}
		return 0;
	};
};

//牛顿法
class Newton : public EquationSolver
{
private:
	double x0,x=0,u=0;
	int M,k=0;
public:
	Newton(double _x0, int _M):x0(_x0),M(_M) {};
	double solve() {
		x = x0;
		for (k = 0; k < M; k++) {
			u = func5(x);
			if (fabs(u) < std::numeric_limits<float>::epsilon()) {
				break;
			}
			x = x - u / diff5(x);
		}
		if (k >=M) {
			std::cout << "不收敛" << std::endl;
		}
		else {
			std::cout << "根为：" << x << std::endl;
			std::cout << "迭代次数为：" << k << std::endl;
		}
		return 0;
	};
};

//割线法
class Secant :public EquationSolver
{
private:
	double x0,x1,delta,u=0,v=0,temp=0,s=0;
	int M,k=0;
public:
	Secant(double _x0, double _x1, double _delta, int _M) :x0(_x0), x1(_x1), delta(_delta), M(_M) {};
	double solve() {
		u = func6(x1);
		v = func6(x0);
		for (k = 2; k < M; k++) {
			if (abs(u) > abs(v)) {
				temp = x0;
				x0 = x1;
				x1 = temp;
				temp = u;
				u = v;
				v = temp;
			}
			s = (x1 - x0) / (u - v);
			x0 = x1;
			v = u;
			x1 = x1 - u * s;
			u = func6(x1);
			if (fabs(x1 - x0) < delta || abs(u) < std::numeric_limits<double>::epsilon())
				break;
		}
		if (k >= M) {
			std::cout << "不收敛" << std::endl;
		}
		else {
			std::cout << "根为：" << x1 << std::endl;
			std::cout << "迭代次数为：" << k << std::endl;
		}
		return 0;
	}
};

